import areaCodes from "./areaCode.json";

// interface IdCardValidEvent {
//     _emptyAndLength: (idCard) => boolean
//     _idCardRule: (idCard) => boolean
//     _checkProvince: (idCard,result[]) => boolean | string
//     _checkCity: (idCard,result[]) => boolean | string
//     _checkBirthday: (idCard,result[]) => boolean
//     _overallValid: (idCard,result[]) => boolean
//     _getInfo: (idCard) => string[]
// }
// implements IdCardValidEvent

export class IdCardValidFun {
  // 第一步 进行非空以及长度校验
  _emptyAndLength(idCard) {
    return !!(idCard && idCard.length === 18);
  }
  // 第二步 进行身份证号规则校验
  // 身份证号是由18位数字或17位数字+x组成
  _idCardRule(idCard) {
    const reg = /(^\d{17}(\d|X)$)/;
    return reg.test(idCard);
  }
  // 第三步 验证省份
  _checkProvince(idCard, result = []) {
    const provinceCity = {
      11: "北京市",
      12: "天津市",
      13: "河北省",
      14: "山西省",
      15: "内蒙古自治区",
      21: "辽宁省",
      22: "吉林省",
      23: "黑龙江省 ",
      31: "上海",
      32: "江苏省",
      33: "浙江省",
      34: "安徽省",
      35: "福建省",
      36: "江西省",
      37: "山东省",
      41: "河南省",
      42: "湖北省 ",
      43: "湖南省",
      44: "广东省",
      45: "广西壮族自治区",
      46: "海南省",
      50: "重庆",
      51: "四川省",
      52: "贵州省",
      53: "云南省",
      54: "西藏自治区 ",
      61: "陕西省",
      62: "甘肃省",
      63: "青海省",
      64: "宁夏回族自治区",
      65: "新疆维吾尔自治区",
      71: "台湾省",
      81: "香港特别行政区",
      82: "澳门特别行政区",
    };
    const province = parseInt(idCard.substring(0, 2));
    result.push(provinceCity[province]);
    return !!provinceCity[province];
  }
  // // 第四步 验证城市以及区县代码 这里的JSON我是在网上下载的,可能还有的代码是一代.
  _checkCity(idCard, result = []) {
    const areaCodesObj = areaCodes;
    const city = parseInt(idCard.substring(0, 6));
    result.push(areaCodesObj[city]);
    return !!areaCodesObj[city];
  }
  // // 第五步 出生日期校验
  _checkBirthday(idCard, result = []) {
    const idCardReg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
    const arrData = idCard.match(idCardReg);
    const year = parseInt(arrData[2]);
    const month = parseInt(arrData[3]);
    const day = parseInt(arrData[4]);
    const birthday = new Date(year + "/" + month + "/" + day);
    // 日期不合法直接不通过校验
    if (
      birthday.getMonth() != 0 &&
      (!birthday.getMonth() || !birthday.getDay())
    ) {
      return false;
    }
    result.push(year + "-" + month + "-" + day);
    const currentData = new Date();
    const currentYear = currentData.getFullYear();
    const age = currentYear - year;
    // 不知道现在小宝宝多久上户口,所以我这里写的是年龄大于0岁的  1岁到200岁之间有效
    return age > 0 && age <= 200;
  }
  // // 所在地派出所的代码就不验证了 实在太多了
  // // 第十七位也没什么好校验的 就一个数字 奇数是男性，偶数是女性
  // // 第七步 校验最后一位校验码
  // // 这里自行百度身份证最后一位的计算方法(固定算法)
  _checkCode(idCard) {
    const factorArray = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    // 对应的最后一位身份证的号码
    const correspondArray = [
      "1",
      "0",
      "X",
      "9",
      "8",
      "7",
      "6",
      "5",
      "4",
      "3",
      "2",
    ];
    let cardTemp = 0;
    for (let i = 0; i < 17; i++) {
      cardTemp += parseInt(idCard.substring(i, i + 1)) * factorArray[i];
    }
    return correspondArray[cardTemp % 11] === idCard.substring(17, 18);
  }
  _overallValid(idCard) {
    // 1 这里如果为空或者没有18位直接返回false
    if (!this._emptyAndLength(idCard)) {
      return false;
    }
    // 2
    if (!this._idCardRule(idCard)) {
      return false;
    }
    // 3
    if (!this._checkProvince(idCard)) {
      return false;
    }
    // 4
    if (!this._checkCity(idCard)) {
      return false;
    }
    // 5
    if (!this._checkBirthday(idCard)) {
      return false;
    }
    // 6
    return this._checkCode(idCard);
  }
  _getInfo(idCard) {
    let result = [];
    if (!this._emptyAndLength(idCard)) {
      return [];
    }
    if (!this._idCardRule(idCard)) {
      return [];
    }
    //  省份
    if (!this._checkProvince(idCard, result)) {
      return [];
    }
    // 县
    if (!this._checkCity(idCard, result)) {
      return [];
    }
    // 年月 日
    if (!this._checkBirthday(idCard, result)) {
      return [];
    }
    if (!this._checkCode(idCard)) {
      return [];
    }
    result.push(parseInt(idCard.substring(17, 18)) % 2 == 0 ? "女" : "男");
    return result;
  }

  checkId(pId) {
    var arrVerifyCode = [1, 0, "x", 9, 8, 7, 6, 5, 4, 3, 2];
    var Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    var Checker = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];
    if (pId.length != 15 && pId.length != 18) return "身份证号共有 15 码或18位";
    var Ai =
      pId.length == 18
        ? pId.substring(0, 17)
        : pId.slice(0, 6) + "19" + pId.slice(6, 16);
    if (!/^\d+$/.test(Ai)) return "身份证除最后一位外，必须为数字！";
    var yyyy = Ai.slice(6, 10),
      mm = Ai.slice(10, 12) - 1,
      dd = Ai.slice(12, 14);
    var d = new Date(yyyy, mm, dd),
      year = d.getFullYear(),
      mon = d.getMonth(),
      day = d.getDate(),
      now = new Date();
    if (
      year != yyyy ||
      mon != mm ||
      day != dd ||
      d > now ||
      now.getFullYear() - year > 140
    )
      return "身份证输入错误！";
    for (var i = 0, ret = 0; i < 17; i++) ret += Ai.charAt(i) * Wi[i];
    Ai += arrVerifyCode[(ret %= 11)];
    return pId.length == 18 && pId.toLowerCase() != Ai
      ? "身份证输入错误！"
      : Ai;
  }

  getInfo(id) {
    //根据身份证取 省份,生日，性别  Go_Rush(阿舜) from http://ashun.cnblogs.com/
    id = this.checkId(id);
    // if (isNaN(id)) return "错误的身份证号码";
    var id = String(id),
      sex = id.slice(14, 17) % 2 ? "男" : "女";
    var prov =
      areaCodes[id.slice(0, 6)] ||
      areaCodes[id.slice(0, 4)] ||
      areaCodes[id.slice(0, 2)] ||
      "无法确定";
    // 计算年龄
    const year = id.substring(6, 10); // 出生年份
    const month = id.substring(10, 12); // 出生月份
    const day = id.substring(12, 14); // 出生日期
    const now = new Date();
    let age = now.getFullYear() - year - 1;
    if (
      now.getMonth() + 1 > month ||
      (now.getMonth() + 1 === month && now.getDate() >= day)
    ) {
      age++;
    }
    // 获取出生日期
    var birthday = new Date(
      id.slice(6, 10),
      id.slice(10, 12) - 1,
      id.slice(12, 14)
    ).toLocaleDateString();
    return [prov, sex, age];
  }
}

const IdCardValid = new IdCardValidFun();

export default IdCardValid;
